home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i052: Usenet news batcher control program (newbatchA)
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: cca!caip!cbmvax!bpa!espo (Bob Esposito)
- Mod.sources: Volume 6, Issue 52
- Archive-name: newbatchA
-
- [ This is the first of two batched news utility programs (BNUP, to coin
- an acronym). It was written on a SystemV machine, but it looks like
- it would be fairly easy to convert to BSD and, e.g., the directory
- library. Stuff dealing with the UUCP queue is much less portable,
- of course, but Bob nicely provides a default mechanism. Take a look
- at the check_uucp routine, however -- I think you may want a different
- default value. Also, I added a modified xerror routine that doesn't
- depend on knowing the internal's of the FILE struct. I haven't
- tested it, but a "grep xerror *." seems to say I'm ok; add -DUSE_PORT_CODE
- for my version. --r$ ]
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # Contents: README nbatcher.1 nbatcher.ctl nbatcher.doc Makefile
- # bst.c checkwork.c define.c logger.c main.c nbatcher.c parse.c
-
- echo x - README
- sed 's/^XX//' > "README" <<'@//E*O*F README//'
- XXThe program provides a better way to handling batching of USENET news
- XXto neighboring sites. It works with 2.10B and later, including
- XX2.10.3B, which provides compression batching.
-
- XXPlease send any questions and bug reports to me (bpa!espo) for
- XXdistribution to the net. This software is public domain, and cannot be
- XXsold for any profit.
-
- XXNbatcher was written for UNIX (trademark of AT&T) System V, but should
- XXbe compatible with most version currently being used today. It is
- XXpresently running on a VAX (trademark of DEC) 11/780 feeding 5 remote
- XXsites with news. Two important issues MUST be noted here.
-
- XXSince nbatcher checks the UUCP directory for each site listed in the
- XXcontrol file, directory configuration should be UUCPDIR/sitename, e.g.
- XX/usr/spool/uucp/foo for site foo. But since not everyone is generic,
- XXI've allowed nbatcher to skip over the UUCP byte counting routine if
- XXthis is not so. In addition to this, some uucpcleanup daemons remove
- XXthe site directory if there's nothing spooled there. When this
- XXhappens, nbatcher will notify you of this and continue on.
-
- XXThe other issue is that you MUST configure your NEWSLIB/sys file using the
- XXbatch syntax as described in the USENET Installation document. Field 3
- XXshould contain the `F' flag indicating a batched transmission for that
- XXsite and field 4 should contain the filename where news article's full
- XXpathname will be appended to. Nbatcher requires that the filename in
- XXfield 4 match the sitename in the control file. For example, the entry:
- XX foo:net,mod,usa,na,to.foo:F:/usr/spool/batchnews/foo
- XXsays that all news articles going to site `foo' will be batched, using
- XXthe file `foo' in /usr/spool/batchnews. Nbatcher's control file entry:
- XX foo:3,14,22:16:150000:
- XXwill get the news article's full pathname from /usr/spool/batchnews/foo
- XXfor batching. This requirement MUST be adhered to for nbatcher to work
- XXcorrectly. I believe most sites that batch news use this type of
- XXconfiguration, since its easy to keep track of a remote site's work.
- XXNote that the name of the directory "/usr/spool/batchnews" is set
- XXin the Makefile.
-
- XXThe manual page describes the control file, as does nbatcher.doc. Note
- XXthat even though nbatcher indicates max bytes has been reached, if that
- XXsite gets compressed batches, the next time nbatcher runs for that site
- XXwork could get scheduled.
-
- XXAlso included is a utility program called "bst," BatchSTatus, which
- XXshows who many news articles are currently in the batch file for each
- XXsystem. Just type "make bst" for that and copy it to where you want,
- XXusually LIBDIR. Note that bst does reads on the directory structure
- XXdirectly.
-
- XXInstallation is simple: look at the first few #define's in nbatcher.h;
- XXalso edit the Makefile for the appropriate BATCHDIR and LIBDIR for your
- XXsite. Type "make" or "make install."
-
- XXNOTE: Read the comments in parse.c concerning MAX_BYTES. This is the
- XXmaximum amount of bytes per site that's allowed in the control file for
- XXqueue_size. Change it at your own risk!
-
- XX Bob Esposito
- XX bpa!espo
- XX Bell of Penna.
- @//E*O*F README//
- chmod u=rw,g=rw,o=rw README
-
- echo x - nbatcher.1
- sed 's/^XX//' > "nbatcher.1" <<'@//E*O*F nbatcher.1//'
- XX.TH NBATCHER 1 LOCAL
- XX.SH NAME
- XXnbatcher \- new batching system for news
- XX.SH SYNOPSIS
- XX.B nbatcher
- XX.IR "(run out of " cron ".)"
- XX.SH DESCRIPTION
- XX.PP
- XX.I Nbatcher
- XXis a program designed to send batched USENET data out in an orderly and
- XXcontrolled fashion, while providing alternative transmission methods.
- XXAs such, it is a replacement for
- XX.I csendbatch
- XXand the like, which typically require many entries in
- XX.IR crontab .
- XX.I Nbatcher
- XXis intended to be run hourly out of
- XX.I cron
- XXas the USENET administrator (NEWSID).
- XX.PP
- XX.I Nbatcher
- XXscans the file
- XX.I nbatcher.ctl
- XXin the NEWSLIB directory to determine if work should be spooled for a system.
- XXIn the control file, lines starting with asterisks are ignored; data lines
- XXare comprised of five colon\-separated fields:
- XX.RS
- XXsite:hour:bits:queue_size:command
- XX.RE
- XX.TP ``site''
- XXName of the USENET neighbor; it is the same as the site in the news
- XX.I sys
- XXfile.
- XX.TP ``hours''
- XXThis field is patterned after
- XX.IR cron 's.
- XXIf the hour is ``off,'' no work is spooled for the site.
- XXAn hour of ``*'' matches every hour.
- XXIt is also possible to specify specific hours, (e.g., 8, 09, or 22), a
- XXcomma\-separated list (e.g., 8,09,22), or a twenty\-four range, like
- XX1-\15 for 10am through 3pm and 22\-4, for 10pm through 4am.
- XX.TP ``bits''
- XXThis field specifies the number of bits to use in compression; it should be
- XXa number between nine and 16, inclusive, or null.
- XXIf a number is specified, it is passed on to the
- XX.I compress
- XXprogram via the ``\-b'' flag.
- XX.TP ``queue_size''
- XXThis field specifies the maximum number of bytes allowed in the UUCP queue
- XXfor this site.
- XXThe default is 100K.
- XXThe UUCP queue size is determined by looking in the
- XX.IR /usr/spool/uucp/ site
- XXdirectory; if it doesn't exist, the check is bypassed.
- XXIf there is data in the UUCP queue,
- XX.I nbatcher
- XXwill only queue up as many USENET transfers as will fit within the limit
- XXspecified by the ``queue_size'' field.
- XX.TP ``command''
- XXThis field is used to specific the UUCP command that should be used to queue
- XXthe job; as distributed, the default is ``uux \- \-r site!rnews''; note the
- XXabsence of the ``\-z'' flag.
- XX.PP
- XXTo set up a USENET neighbor to be controlled by
- XX.IR nbatcher ,
- XXthe news
- XX.I sys
- XXentry for the neighbor must be modified to specify the ``F'' flag, and the
- XXfile used to contain the article names must be
- XX.RI BATCHDIR/sysname ,
- XXwhere BATCHDIR is set in the Makefile as distributed.
- XX.SH FILES
- XX.TP NEWSLIB/nbatcher.log
- XXA logfile of failures, postponements, etc.
- XX.SH BUGS
- XXParsing of the control file is fairly robust, but not perfect.
- @//E*O*F nbatcher.1//
- chmod u=rw,g=rw,o=rw nbatcher.1
-
- echo x - nbatcher.ctl
- sed 's/^XX//' > "nbatcher.ctl" <<'@//E*O*F nbatcher.ctl//'
- XX*
- XX* NBATCHER.CTL
- XX* Edit and install in your NEWSLIB directory.
- XX*
- XX* Comments start with *; data lines look like:
- XX* site:hours:bits:queue_size:command
- XX* Where
- XX* site = name of the remote site
- XX* hour = when to do work (* is all, off is never, 22-4 is ok)
- XX* bits = passed on to compress via -b; null gets default
- XX* queue_size = Max # bytes allowed in UUCP queue before postponing
- XX* command = optional command line
- XX*
- XX* See manpage and README for more info.
- @//E*O*F nbatcher.ctl//
- chmod u=rw,g=rw,o=rw nbatcher.ctl
-
- echo x - nbatcher.doc
- sed 's/^XX//' > "nbatcher.doc" <<'@//E*O*F nbatcher.doc//'
-
- XXDETAILED DESCRIPTION OF "NBATCHER.CTL" FILE
- XX-------------------------------------------
-
- XXAs distributed, nbatcher.ctl contains just a terse summary of its
- XXformat. For each site you feed news to, providing that site uses the
- XX":F:BATCHDIR/site" batching syntax in the sys file, a corresponding
- XXentry should exist in nbatcher.ctl Each line is a five-field,
- XXcolon-separated entry indicating what to do for that site. The default
- XXfor BATCHDIR is /usr/spool/batchnews.
-
- XXThe format is:
- XX site:hour:bits:queue_size:command
- XXThe site field is the name of the UUCP site that will get the batched
- XXnews. There MUST be a file in the BATCHDIR directory with the
- XXsitename. Nbatcher will complain about mismatches. This file contains
- XXa full-path listing of the files to batch.
-
- XXNext is the hour field. The syntax directly imitates the crontab entry
- XXfor hour. If hour = "*", than assume a match for every hour. If hour
- XX= "off", then no work is ever spooled for this site. (This is the only
- XXdifference from crontab). You can specify a specific hour, like 8 or
- XX09 or 22. Or a range of hours, like 10-15, meaning check for work from
- XX10am thru 3pm. You can also cycle thru a 24-hour period by saying
- XX22-4, which matches for 10pm thru 4am. Also, hours comma separated
- XXlike 7,14,21, says check for work at 7 AM, 4PM and 9PM only. This
- XXgives lots of flexibility for sites that feed multiple remotes.
-
- XXNext is the bits field, which has a value of 9-16, or may be left blank.
- XXIf non-null, this field is directly passed on to compress with the -b
- XXflag. If it is null, then no compression is done for this site.
-
- XXThe queue_size field is the maximum number of bytes allowed on the UUCP
- XXqueue at any time. It defaults to 100K bytes, and if it's greater than
- XX1MB (see parse.c about MAX_BYTES), than it uses 1MB as the default
- XXnumber of bytes.
-
- XXWhat nbatcher does is first check the UUCPDIR for that site and sums up
- XXthe number of bytes already on-queue. The size of each news article is
- XXaccumulated prior to batching to the tempfile, and this accumulation +
- XXthe UUCP on-queue bytes are checked to see if they surpass the queue_size
- XXvalue. If not, things proceed normally. But if it would exceed the
- XXmax value, then spool what's already been batched, and save the
- XXremainder of the articles for the next scheduled batch.
-
- XXThis is so noted in the nbatcher.log file, showing the UUCP bytes that
- XXwere on-queue (if any), and the number of bytes that were spooled.
- XXAlso, if nbatcher is run from a terminal instead of from cron, a copy
- XXof what gets logged is sent to the terminal.
-
- XXThe last field is the command field. This optional field is used for
- XXspecific UUCP command execution. As written, it defaults to "uux - -r
- XXsite!rnews". Since my uux doesn't require the -z option for rnews, I
- XXleft it out of the UUX define in nbatcher.h This can easily be changed
- XXfor your own taste, or just use the command field.
-
- XXExample:
- XX site-A:3,10:16:450000:
- XXCheck for work for site-A at 3AM and 10AM. Use compress with
- XX16 bits and only spool up to 450K bytes, using "uux - -r site-A!rnews".
-
- XXAnother example:
- XX foo:23-4::300000:uux - -r -z foo!rnews
- XXCheck for work for foo between 11PM and 4AM. No compression is used
- XXand spool up to 300K bytes using the command field.
-
- XXThis format should help ease UUCP congestion on the local site for
- XXnews. I currently feed 5 remote sites, compressed and non-compressed
- XXformats, and have noticed a vast improvement in disk space as well as
- XXout port availability for UUCP. It has allowed me to check for work
- XXfor all sites every hour, since there's a limit on how much gets
- XXqueued. And if the remote doesn't answer on the hourly UUCP poll, so
- XXwhat! Nbatcher just won't spool any more until the queue_size limit
- XXon-queue is reduced.
-
- XXNbatcher was designed to weed out any illegal syntax in the control
- XXfile, but it's not bug-proof, so use some discretion.
-
- XXBob Esposito
- XXBell of Penna.
- XXJune 1986
- @//E*O*F nbatcher.doc//
- chmod u=rw,g=rw,o=rw nbatcher.doc
-
- echo x - Makefile
- sed 's/^XX//' > "Makefile" <<'@//E*O*F Makefile//'
- XX#
- XX# Makefile for nbatcher
- XX#
- XX# R.J. Esposito
- XX# Bell of Penna.
- XX# June 1986
- XX#
-
- XX# You MUST define BATCHDIR as the place where USENET
- XX# puts the articles to be batched.
- XX#
- XX# LIBDIR is where you USENET library is and also
- XX# MUST be defined.
-
- XXBATCHDIR = /usr/spool/batchnews
- XXLIBDIR = /misc/lib/usenet
-
- XXCFLAGS = -O -c
- XXLFLAGS = -s
- XXDFLAGS = -DBATCHDIR='"$(BATCHDIR)"' -DLIBDIR='"$(LIBDIR)"'
-
- XXOBJS = define.o main.o parse.o checkwork.o nbatcher.o logger.o
-
- XXSRC = define.c main.c parse.c checkwork.c nbatcher.c logger.c nbatcher.h bst.c
- XXDOCS = README nbatcher.ctl nbatcher.doc
-
- XXall: $(OBJS)
- XX $(CC) $(DFLAGS) $(LFLAGS) -o nbatcher $(OBJS)
- XX chmod 0755 nbatcher
-
- XXinstall: all
- XX cp nbatcher $(LIBDIR)
- XX chmod 0755 $(LIBDIR)/nbatcher
- XX cp nbatcher.ctl $(LIBDIR)/nbatcher.ctl
- XX chmod 0644 $(LIBDIR)/nbatcher.ctl
-
- XXdefine.o: nbatcher.h define.c
- XX $(CC) $(CFLAGS) $(DFLAGS) define.c
-
- XXmain.o: nbatcher.h main.c
- XX $(CC) $(CFLAGS) $(DFLAGS) main.c
-
- XXparse.o: nbatcher.h parse.c
- XX $(CC) $(CFLAGS) $(DFLAGS) parse.c
-
- XXcheckwork.o: nbatcher.h checkwork.c
- XX $(CC) $(CFLAGS) $(DFLAGS) checkwork.c
-
- XXnbatcher.o: nbatcher.h nbatcher.c
- XX $(CC) $(CFLAGS) $(DFLAGS) nbatcher.c
-
- XXlogger.o: nbatcher.h logger.c
- XX $(CC) $(CFLAGS) $(DFLAGS) logger.c
-
- XXbst: bst.c
- XX $(CC) $(CFLAGS) $(DFLAGS) bst.c
- XX $(CC) $(LFLAGS) -o bst bst.o
-
- XXclean:
- XX rm -f *.o *.shar
-
- XXclobber: clean
- XX rm -f nbatcher
-
-
- XXshar:
- XX shar -v $(SRC) $(DOCS) Makefile > nbatcher.shar
- @//E*O*F Makefile//
- chmod u=rw,g=rw,o=rw Makefile
-
- echo x - bst.c
- sed 's/^XX//' > "bst.c" <<'@//E*O*F bst.c//'
- XX/*
- XX * bst.c - a utility for indicating how many
- XX * news articles are ready for batching
- XX * for each site in the BACTHDIR directory.
- XX *
- XX * R.J. Esposito
- XX * Bell of Penna.
- XX * June 1986
- XX *
- XX */
-
- XX#include <stdio.h>
- XX#include <sys/types.h>
- XX#include <sys/stat.h>
- XX#include <sys/dir.h>
-
-
- XXchar buf[512];
- XXFILE *dd;
- XXstruct direct dp;
- XXstruct stat st;
-
- XXmain()
- XX{
- XX int fd, j;
- XX int bcnt, lcnt;
-
- XX if(chdir(BATCHDIR) != 0) {
- XX perror(BATCHDIR);
- XX exit(1);
- XX }
-
- XX if((dd=fopen(".", "r")) == NULL) {
- XX printf("can't open %s\n", BATCHDIR);
- XX exit(1);
- XX }
-
- XX while((fread((char *)&dp, sizeof(dp), 1, dd)) == 1) {
- XX if(dp.d_ino == 0 || dp.d_name[0] == '.')
- XX continue;
- XX if(stat(dp.d_name, &st) != 0) {
- XX printf("can't stat %s\n", dp.d_name);
- XX exit(1);
- XX }
- XX if(st.st_size <= 0 )
- XX continue;
- XX if((fd=open(dp.d_name, 0)) < 0) {
- XX printf("can't open %s\n", dp.d_name);
- XX exit(1);
- XX }
- XX lcnt = 0;
- XX while((bcnt=read(fd,buf,512)) > 0) {
- XX for(j=0; j<=bcnt; j++)
- XX if(buf[j] == '\n')
- XX lcnt += 1;
- XX }
- XX close(fd);
- XX printf("%s\t %d article", dp.d_name, lcnt);
- XX printf("%c\n", lcnt > 1 ? 's' : ' ');
- XX }
- XX}
- @//E*O*F bst.c//
- chmod u=rw,g=rw,o=rw bst.c
-
- echo x - checkwork.c
- sed 's/^XX//' > "checkwork.c" <<'@//E*O*F checkwork.c//'
- XX/*
- XX *
- XX * checkwork.c - look to see if there's any work
- XX * to do for a site.
- XX *
- XX * R.J. Esposito
- XX * Bell of Penna.
- XX * June 1986
- XX *
- XX */
-
- XX#include <stdio.h>
- XX#include <sys/types.h>
- XX#include <sys/stat.h>
- XX#include <sys/utsname.h>
- XX#include <sys/dir.h>
- XX#include <ctype.h>
- XX#include <time.h>
- XX#include "nbatcher.h"
-
- XXwork_to_do ()
- XX{
- XX register char *p;
- XX struct tm *localtime(), *tp;
- XX struct stat st;
- XX char buf[BUFSIZ];
- XX long time(), clock;
- XX int hour;
- XX short num, upper, lower;
-
- XX sprintf (buf, "%s/%s", BATCHDIR, ep.site);
-
- XX if (stat(buf, &st) < 0)
- XX xerror ("bad stat on %s\n", buf);
-
- XX /* if the size of the batch file is
- XX zero, return FALSE
- XX */
-
- XX if (st.st_size == 0)
- XX return (FALSE);
-
- XX /* now see if it time to do anything */
-
- XX clock = time ((long *)0);
- XX tp = localtime (&clock);
- XX hour = tp->tm_hour;
-
- XX p = (char *) ep.hour;
-
- XX if (*p == '*') /* match any hour */
- XX return (check_uucp());
-
- XX if (strncmp(p, "off", 3) == 0) /* just what it says, off */
- XX return (FALSE);
-
- XX /* parse thru hour field to see if
- XX this is the hour to do work */
-
- XX num = 0;
- XX do {
- XX num = num*10 + (*p - '0');
- XX } while (isdigit(*++p));
- XX if (num == hour)
- XX return (check_uucp());
-
- XX if (*p == '-') {
- XX lower = num;
- XX p++;
- XX num = 0;
- XX do {
- XX num = num*10 + (*p - '0');
- XX } while (isdigit(*++p));
- XX upper = num;
-
- XX if (lower < upper) { /* normal hour range */
- XX if (hour >= lower && hour <= upper)
- XX return (check_uucp());
- XX } else if (lower > upper) { /* 24 hr. cycle thru */
- XX if (hour >= lower || hour <= upper)
- XX return (TRUE);
- XX } else
- XX return (FALSE);
- XX }
-
- XX if (*p == ',') {
- XX p++;
- XX while (*p) {
- XX num = 0;
- XX do {
- XX num = num*10 + (*p - '0');
- XX } while (isdigit(*++p));
- XX if (num == hour)
- XX return (check_uucp());
- XX p++;
- XX }
- XX }
-
- XX return (FALSE);
- XX}
-
- XX/* If check_uucp cannot find the remote site
- XX * directory, just bypass the byte counting
- XX * routine. This is necessary because the
- XX * uucpcleanup daemon, on some sites, removes
- XX * the site directory when there's nothing there.
- XX */
-
- XXcheck_uucp()
- XX{
- XX struct utsname utsn;
- XX struct direct dp;
- XX struct stat st;
- XX FILE *dfp;
- XX char u_name[9], buf[80];
- XX short prefix_len;
-
- XX if (uname(&utsn) < 0)
- XX xerror ("can't get local nodename\n");
-
- XX sprintf (buf, "%s/%s", UUCPDIR, ep.site);
- XX if (chdir(buf) < 0) {
- XX fprintf (stderr, "nbatcher: can't chdir to %s - bypassing UUCP check\n", buf);
- XX return (TRUE);
- XX }
-
- XX if ((dfp=fopen(".", "r")) == NULL) {
- XX fprintf (stderr, "nbatcher: fopen error on %s - bypassing UUCP check\n", UUCPDIR);
- XX return (TRUE);
- XX }
-
- XX sprintf (buf, "D.%s", utsn.nodename);
- XX prefix_len = (short) strlen(buf);
- XX n_bytes = 0;
- XX while ((fread((char *)&dp, sizeof(dp), 1, dfp)) == 1) {
- XX if (dp.d_ino == 0 || dp.d_name[0] == '.')
- XX continue;
- XX if (strncmp(dp.d_name, buf, prefix_len))
- XX continue;
- XX if (stat(dp.d_name, &st) < 0) {
- XX fprintf (stderr, "nbatcher: bad stat on UUCP_file %s - bypassing\n", dp.d_name);
- XX continue;
- XX }
- XX n_bytes += st.st_size;
- XX if (n_bytes > ep.m_bytes) {
- XX fclose (dfp);
- XX return (FALSE);
- XX }
- XX }
- XX fclose (dfp);
- XX if (chdir(LIBDIR) < 0)
- XX xerror ("can't chdir back to %s\n", LIBDIR);
-
- XX return (TRUE);
- XX}
- @//E*O*F checkwork.c//
- chmod u=rw,g=rw,o=rw checkwork.c
-
- echo x - define.c
- sed 's/^XX//' > "define.c" <<'@//E*O*F define.c//'
- XX/*
- XX * define.c - global defines for nbatcher.
- XX *
- XX * R.J. Esposito
- XX * Bell of Penna.
- XX * June 1986
- XX *
- XX */
-
- XX#include <stdio.h>
- XX#include "nbatcher.h"
-
- XXFILE *lfp,
- XX *tfp,
- XX *log = NULL;
-
- XXlong n_bytes,
- XX cu_bytes;
-
- XXchar *tfile = NULL;
-
- XXshort vflg = 0,
- XX nfiles = 10;
-
- XXint fcnt = 0,
- XX scnt = 0;
-
- @//E*O*F define.c//
- chmod u=rw,g=rw,o=rw define.c
-
- echo x - logger.c
- sed 's/^XX//' > "logger.c" <<'@//E*O*F logger.c//'
- XX/*
- XX *
- XX * logger.c - log info about nbatcher
- XX *
- XX * R.J. Esposito
- XX * Bell of Penna.
- XX * June 1986
- XX *
- XX */
-
- XX#include <stdio.h>
- XX#include <time.h>
- XX#include "nbatcher.h"
-
- XXlog_it (bytes)
- XXlong bytes;
- XX{
- XX struct tm *localtime(), *tp;
- XX long time(), clock;
- XX char logfile[80], buf[BUFSIZ];
- XX char pbuf[BUFSIZ];
-
- XX sprintf (logfile, "%s/%s", LIBDIR, "nbatcher.log");
- XX if (log == NULL) {
- XX if ((log=fopen(logfile, "a")) == NULL)
- XX fprintf (stderr, "can't append to logfile\n");
- XX }
-
- XX rewind (log, 0L, 2); /* just incase */
-
- XX clock = time ((long *)0);
- XX tp = localtime (&clock);
- XX sprintf (buf, "%.2d/%.2d %.2d:%.2d %s: %d %s batched, %d %s queued\n",
- XX tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, ep.site,
- XX fcnt, (fcnt==1 ? "file" : "files"), scnt,
- XX (scnt==1 ? "file" : "files"));
-
- XX if (bytes)
- XX sprintf (pbuf, "%s\tmax bytes reached. UUCP bytes was %ld, byte count = %ld\n",
- XX buf, n_bytes, bytes);
- XX else
- XX sprintf (pbuf, "%s", buf);
-
- XX if (vflg)
- XX fprintf (stdout, "%s",pbuf);
-
- XX if (log != NULL)
- XX fputs (pbuf, log);
-
- XX}
- @//E*O*F logger.c//
- chmod u=rw,g=rw,o=rw logger.c
-
- echo x - main.c
- sed 's/^XX//' > "main.c" <<'@//E*O*F main.c//'
- XX/*
- XX *
- XX * main.c - for nbatcher
- XX *
- XX * R.J. Esposito
- XX * Bell of Penna.
- XX * June 1986
- XX *
- XX */
-
- XX#include <stdio.h>
- XX#include "nbatcher.h"
-
- XXmain()
- XX{
- XX int uid;
- XX FILE *cfp;
- XX char fbuf[BUFSIZ];
-
- XX uid = getuid();
-
- XX if (uid && uid != NEWSUID)
- XX xerror ("permission denied - not NEWSUSER\n");
-
- XX if (chdir(LIBDIR) < 0)
- XX xerror ("can't chdir to %s\n", LIBDIR);
-
- XX if ((cfp=fopen("nbatcher.ctl", "r")) == NULL)
- XX xerror ("no `batcher.ctl' file found\n");
-
- XX if (isatty(0))
- XX vflg = TRUE;
-
- XX while ((fgets(fbuf, sizeof(fbuf), cfp)) != NULL) {
- XX if (fbuf[0] == '*' || fbuf[0] == '\n')
- XX continue;
- XX parse_entry (fbuf);
- XX if (!work_to_do())
- XX continue;
- XX batch_it ();
- XX }
-
- XX fclose (cfp);
- XX unlink (tfile);
- XX exit (0);
- XX}
- XX
- @//E*O*F main.c//
- chmod u=rw,g=rw,o=rw main.c
-
- echo x - nbatcher.c
- sed 's/^XX//' > "nbatcher.c" <<'@//E*O*F nbatcher.c//'
- XX/*
- XX *
- XX * nbatcher.c - where it really happens.
- XX *
- XX * R.J. Esposito
- XX * Bell of Penna.
- XX * June 1986
- XX *
- XX */
-
- XX#include <stdio.h>
- XX#include <sys/types.h>
- XX#include <sys/stat.h>
- XX#include <time.h>
- XX#include "nbatcher.h"
-
- XXbatch_it ()
- XX{
- XX struct stat st;
- XX FILE *bfp, *afp;
- XX char fbuf[BUFSIZ], lckfile[40];
- XX char tbuf[80];
- XX short count;
- XX int c;
-
- XX if (chdir(BATCHDIR) < 0)
- XX xerror ("can't chdir to %s\n", BATCHDIR);
-
- XX /* we create a lock file for two purposes,
- XX first to make sure a previous nbatcher
- XX didn't blowup and leave the lock file
- XX laying around, and second to put the
- XX remaining news article filenames when
- XX we go over the max UUCP bytes and there's
- XX still files remaining for batching.
- XX */
-
- XX sprintf (lckfile, ".%s.lock", ep.site);
- XX if (!access(lckfile, 0))
- XX xerror ("lockfile already exists for %s\n", ep.site);
-
- XX if ((lfp=fopen(lckfile, "w")) == NULL)
- XX xerror ("can't create lockfile for %s\n", ep.site);
-
- XX /* now that we've locked ourselves for this site,
- XX lets carry on */
-
- XX if ((bfp=fopen(ep.site, "r")) == NULL)
- XX xerror ("can't open %s/%s for reading\n", BATCHDIR, ep.site);
-
- XX if (tfile == NULL) {
- XX tfile = mktemp("/tmp/bnewsXXXXXX");
- XX if ((tfp=fopen(tfile, "w")) == NULL)
- XX xerror ("can't open %s for writing\n", tfile);
- XX }
-
- XX count = fcnt = scnt = 0;
- XX cu_bytes = 0;
- XX while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL) {
- XX fbuf[strlen(fbuf)-1] = '\0'; /* remove the newline */
- XX if ((afp=fopen(fbuf, "r")) == NULL) {
- XX fprintf (stderr, "bypassing article %s: can't read it\n",
- XX fbuf);
- XX continue;
- XX }
- XX if (fstat (fileno(afp), &st) < 0)
- XX xerror ("fstat failed on %s\n", fbuf);
- XX cu_bytes += st.st_size;
-
- XX /* if the max byte count is exceeded,
- XX save the remaining files for later */
-
- XX if ((cu_bytes + n_bytes) > ep.m_bytes) {
- XX fprintf (lfp, "%s\n", fbuf); /* put the '\n' back */
- XX while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL)
- XX fputs (fbuf, lfp);
- XX fclose (bfp);
- XX fclose (lfp);
- XX fclose (afp);
- XX unlink (ep.site);
- XX if (link(lckfile, ep.site) < 0)
- XX xerror ("can't link lockfile to %s\n", ep.site);
- XX unlink (lckfile);
- XX chown (ep.site, NEWSUID, NEWSGID);
- XX if (count)
- XX spoolit ();
- XX if (cu_bytes - st.st_size)
- XX log_it (cu_bytes - st.st_size);
- XX return;
- XX }
- XX sprintf (tbuf, "#! rnews %ld\n", st.st_size);
- XX fputs (tbuf, tfp);
- XX while ((c=getc(afp)) != EOF)
- XX putc (c, tfp);
- XX fclose (afp);
-
- XX if (++count == nfiles) {
- XX spoolit ();
- XX count = 0;
- XX }
- XX fcnt++;
- XX }
-
- XX /* The final spool if less than nfiles
- XX is encountered. The zero out the
- XX batchfile and unlink the lock file */
-
- XX spoolit ();
- XX close (creat(ep.site, 0664));
- XX chown (ep.site, NEWSUID, NEWSGID);
- XX unlink (lckfile);
-
- XX /* here we log what we've done, and
- XX if vflg is set, a copy to stdout
- XX as well */
-
- XX log_it (0);
- XX if (chdir(LIBDIR) < 0)
- XX xerror ("can't chdir back to %s\n", LIBDIR);
-
- XX}
-
- XXspoolit ()
- XX{
- XX struct stat st;
- XX char cmd[BUFSIZ], cfile[80];
- XX FILE *pfp;
- XX int c;
-
- XX fclose (tfp);
- XX stat (tfile, &st);
-
- XX /* if for some reason the temp file
- XX is zero, just return */
-
- XX if (st.st_size == 0)
- XX return;
-
- XX /* if ep.c_bits is set use COMPRESS to compress
- XX the temp file first
- XX */
-
- XX if (ep.c_bits) {
- XX sprintf (cmd, "%s -b%d %s", COMPRESS, ep.c_bits, tfile);
- XX if (system(cmd) != 0)
- XX xerror ("system(%s) failed\n", cmd);
-
- XX strcpy (cfile, tfile);
- XX strcat (cfile, ".Z");
- XX if ((tfp=fopen(cfile, "r")) == NULL)
- XX xerror ("can't open %s for reading\n", cfile);
-
- XX /* if ep.command has a specific command
- XX for UUCP spooling, use it. If not,
- XX use UUX.
- XX */
-
- XX if (ep.command[0] != '\0')
- XX strcpy (cmd, ep.command);
- XX else
- XX sprintf (cmd, "%s %s!rnews", UUX, ep.site);
-
- XX /* now popen the command for writing
- XX and send it the contents of tempfile */
-
- XX if ((pfp=popen(cmd, "w")) == NULL)
- XX xerror ("popen failed on %s\n", cmd);
-
- XX /********************************************
- XX * for version 2.10.3 and above,
- XX * prepend `#! cunbatch'.
- XX *
- XX * NOTE: The remote site MUST be able to
- XX * except this format, or it will
- XX * be lost!!!
- XX *******************************************/
-
- XX fputs ("#! cunbatch\n", pfp);
- XX while ((c=getc(tfp)) != EOF)
- XX putc (c, pfp);
-
- XX pclose (pfp);
- XX fclose (tfp);
- XX unlink (cfile);
- XX } else { /* regular batching here */
- XX if ((tfp=fopen(tfile, "r")) == NULL)
- XX xerror ("can't open %s for reading\n", tfile);
-
- XX /* if ep.command has a specific command
- XX for UUCP spooling, use it. If not,
- XX use UUX.
- XX */
-
- XX if (ep.command[0] != '\0')
- XX strcpy (cmd, ep.command);
- XX else
- XX sprintf (cmd, "%s %s!rnews", UUX, ep.site);
-
- XX if ((pfp=popen(cmd, "w")) == NULL)
- XX xerror ("popen failed on %s\n", cmd);
-
- XX while ((c=getc(tfp)) != EOF)
- XX putc (c, pfp);
-
- XX pclose (pfp);
- XX fclose (tfp);
- XX }
- XX if ((tfp=fopen(tfile, "w")) == NULL)
- XX xerror ("can't re-open %s\n", tfile);
-
- XX scnt++;
- XX}
- @//E*O*F nbatcher.c//
- chmod u=rw,g=rw,o=rw nbatcher.c
-
- echo x - parse.c
- sed 's/^XX//' > "parse.c" <<'@//E*O*F parse.c//'
- XX/*
- XX *
- XX * parse.c - nbatcher line parser for the control file
- XX *
- XX *
- XX * R.J. Esposito
- XX * Bell of Penna.
- XX * June 1986
- XX *
- XX */
-
- XX#include <stdio.h>
- XX#include <sys/types.h>
- XX#include <ctype.h>
- XX#include "nbatcher.h"
-
- XX#define MAX_BYTES 1000000L /* max allowable bytes */
-
- XXparse_entry (line)
- XXchar *line;
- XX{
- XX register char *p;
- XX short num, upper;
- XX short lower, dash;
- XX long l_num;
-
- XX upper = 23; /* upper hour limit */
- XX lower = 0; /* lower hour limit */
- XX dash = 0;
-
- XX clear_entry (&ep); /* zero out the structure */
-
- XX p = (char *) ep.site;
-
- XX /* get the site name and copy
- XX it to the structure */
-
- XX while (*line && *line != COLON)
- XX *p++ = *line++;
- XX *p = '\0';
- XX if (*++line == '\n' || *line == '\0')
- XX xerror ("illegal number of fields\n");
-
- XX /* check that its valid */
-
- XX if (ep.site[0] == '\0')
- XX xerror ("null site name in control file\n");
-
- XX /* now, parse the hour string and check
- XX for valid syntax */
-
- XX p = (char *) ep.hour;
- XX while (*line && *line != COLON)
- XX *p++ = *line++;
-
- XX *p = '\0';
- XX if (*++line == '\n' || *line == '\0')
- XX xerror ("illegal number of fields\n");
-
- XX if (ep.hour[0] == '\0')
- XX xerror ("null hour string in control file\n");
-
- XX /* now re-scan the hour in structure and
- XX weed out the badies */
-
- XX if (ep.hour[0] == '*' && ep.hour[1] != '\0')
- XX xerror ("invalid hour string syntax: %s\n", ep.hour);
- XX else if (ep.hour[0] == '*')
- XX goto h_skip;
-
- XX if (strcmp(ep.hour, "off", 3) == 0 && ep.hour[3] != '\0')
- XX xerror ("invalid hour string syntax: %s\n", ep.hour);
- XX else if (strncmp(ep.hour, "off", 3) == 0)
- XX goto h_skip;
-
- XX p = (char *) ep.hour;
- XX if (!isdigit(*p))
- XX xerror ("non-numeric char in hour string: %c\n", *p);
-
- XX while (*p) {
- XX num = 0;
- XX do {
- XX num = num*10 + (*p - '0');
- XX } while (isdigit(*++p));
-
- XX if (num < lower || num > upper)
- XX xerror ("illegal hour: %d\n", num);
-
- XX if (!*p)
- XX break;
-
- XX if (*p == '-' && dash)
- XX xerror ("syntax error in hour field\n");
- XX else if (*p == '-')
- XX dash = TRUE;
-
- XX if (*p != ',' && *p != '-')
- XX xerror ("non-numeric char in hour string: %c\n", *p);
- XX else if (!isdigit(*++p))
- XX xerror ("syntax error in hour field\n");
-
- XX }
-
- XX /* now that thats over with, let do the compression
- XX field. Only 9-16 is allowed, except a null field
- XX indicates no compression for this site. */
-
- XXh_skip:
- XX num = 0;
- XX while (*line && *line != COLON) {
- XX if (!isdigit(*line))
- XX xerror ("non-numeric in compression field\n");
- XX num = num*10 + (*line++ - '0');
- XX }
- XX if (*++line == '\n' || *line == '\0')
- XX xerror ("illegal number of fields\n");
-
- XX if (num != 0 && (num < 9 || num > 16))
- XX xerror ("illegal compression bits: %d\n", num);
-
- XX ep.c_bits = num;
-
- XX /* now check the max. bytes for UUCP queue.
- XX Note: There is a max. allowable # of bytes
- XX here, set at 1MB. Change it at your
- XX own risk.
- XX */
-
- XX l_num = 0;
- XX while (*line && *line != COLON) {
- XX if (!isdigit(*line))
- XX xerror ("non-numeric in max. bytes field\n");
-
- XX l_num = l_num*10 + (*line++ - '0');
- XX }
-
- XX if (l_num > MAX_BYTES)
- XX xerror ("%ld max. bytes exceeds allowable maximun\n", l_num);
-
- XX if (l_num != 0)
- XX ep.m_bytes = l_num;
- XX else
- XX ep.m_bytes = DFL_BYTES;
-
- XX /* and finally the command line (if there is one) */
-
- XX p = (char *) ep.command;
-
- XX if (*++line != '\n' && *line != '\0') {
- XX while (*line && *line != '\n')
- XX *p++ = *line++;
-
- XX *p = '\0';
- XX }
- XX}
-
- XX#ifdef USE_PORT_CODE
- XXxerror (fmt, a1, a2)
- XXchar *fmt;
- XXchar *a1, *a2;
- XX{
- XX char buf[BUFSIZ];
-
- XX sprintf (buf, fmt, a1, a2);
- XX printf ("nbatcher: %s\n", fmt);
- XX exit (99);
- XX}
-
- XX#else
- XXxerror (fmt, argp)
- XXchar *fmt;
- XXint argp;
- XX{
- XX char buf[BUFSIZ];
- XX char fbuf[BUFSIZ];
- XX FILE prwbuf;
- XX register char *cp;
- XX
- XX prwbuf._flag = _IOWRT;
- XX prwbuf._file = _NFILE;
- XX prwbuf._cnt = 32767;
- XX prwbuf._ptr = (unsigned char *)buf;
- XX prwbuf._base = (unsigned char *)buf;
- XX sprintf (fbuf, "%s: %s", "nbatcher", fmt);
- XX _doprnt (fbuf, (char *)&argp, &prwbuf);
- XX putc ('\0', &prwbuf);
- XX for (cp = buf; *cp != '\0'; cp++)
- XX putchar (*cp);
-
- XX exit (99);
- XX}
- XX#endif /* USE_PORT_CODE */
-
- XXclear_entry (s)
- XXchar *s;
- XX{
- XX register int i;
-
- XX for (i=0; i<sizeof(struct file_entry); *s++ = '\0', i++)
- XX ;
-
- XX}
- @//E*O*F parse.c//
- chmod u=rw,g=rw,o=rw parse.c
-
- echo Inspecting for damage in transit...
- temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 60 480 3043 README
- 76 441 2526 nbatcher.1
- 14 88 459 nbatcher.ctl
- 81 678 3907 nbatcher.doc
- 67 185 1387 Makefile
- 61 159 1088 bst.c
- 155 501 3094 checkwork.c
- 27 52 284 define.c
- 50 148 1022 logger.c
- 47 103 699 main.c
- 212 696 4805 nbatcher.c
- 202 668 4011 parse.c
- 1052 4199 26325 total
- !!!
- wc README nbatcher.1 nbatcher.ctl nbatcher.doc Makefile bst.c checkwork.c define.c logger.c main.c nbatcher.c parse.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if test -s $dtemp
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
-